package com.small.os.minio.controller;

import com.alibaba.nacos.common.utils.MD5Utils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.common.basis.exception.BusinessException;
import com.small.os.minio.entity.*;
import com.small.os.minio.entity.vo.*;
import com.small.os.minio.enums.AqUploadStartEnum;
import com.small.os.minio.service.*;
import com.small.os.minio.util.MinIoUtils;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.common.basis.result.*;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 网盘
 *
 * @author wangguochao
 */
@RestController
@AllArgsConstructor
@RequestMapping("/minio")
public class MinioController {

    private final IAqUploadService iAqUploadService;
    private final IAqShareService iAqShareService;
    private final IAqShareInfoService iAqShareInfoService;
    private final IAqFileService iAqFileService;
    private final IAqShareFavoritesService iAqShareFavoritesService;

    /**
     * 分片上传文件
     * 1、续传
     * 2、秒传
     */
    @PostMapping("init-chunk-upload")
    public Result<?> uploadFilesInPieces(@RequestBody AqUploadInit aqUpload) {
        Map<String, Object> map = iAqUploadService.uploadFilesInPieces(aqUpload);
        return ResultSet.go(map);
    }

    /**
     * 合并文件并返回文件信息
     */
    @PostMapping("compose-file")
    public Result<?> composeFile(@RequestBody @Validated AqUploadCompose param) {
        iAqUploadService.composeFile(param);
        return ResultSet.go(param);
    }

    /**
     * 获取文件列
     *
     * @param parentIds 文件夹路径
     */
    @GetMapping()
    public Result<List<AqUpload>> findByPath(@RequestParam(required = false) String parentIds) {
        List<AqUpload> byPath = iAqUploadService.findByPath(parentIds);
        return ResultSet.go(byPath);
    }

    /**
     * 获取文件列-分页[法律法规、规章制度]
     */
    @GetMapping("page-by-path")
    public ResultPage<AqUpload> pageByPath(MinioQ param) {
        IPage<AqUpload> byPath = iAqUploadService.pageByPath(param);
        return ResultSet.page(byPath);
    }

    /**
     * 文件搜索
     */
    @GetMapping("find-by-name")
    public ResultPage<AqUpload> findByName(AqUploadQ param) {
        LambdaQueryWrapper<AqUpload> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(AqUpload::getFileName, param.getFileName())
                .orderByDesc(AqUpload::getIsDir);
        IPage<AqUpload> page = iAqUploadService.page(param.page(), wrapper);
        return ResultSet.page(page);
    }

    /**
     * 删除文件
     * 同时删除分享部分
     *
     * @param id id
     */
    @DeleteMapping()
    public Result<?> delObject(@RequestParam String id) {
        AqUpload byId = iAqUploadService.getById(id);
        boolean b = iAqUploadService.removeById(id);
        iAqShareInfoService.delByMd5(byId.getFileMd5());
        return ResultSet.operation(b);
    }

    /**
     * 分享
     *
     * @param param 分享实体
     */
    @PostMapping("share")
    public Result<AqShare> share(@RequestBody @Validated AqShare param) {
        param.setExpiry(10080);
        AqShare aqShare = iAqShareService.createShare(param);
        return ResultSet.go(aqShare);
    }

    /**
     * 分享列表
     */
    @GetMapping("find-share")
    public ResultPage<AqShare> findShare(AqShareQ param) {
        LambdaQueryWrapper<AqShare> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(param.getShareType() != null,
                AqShare::getShareType, param.getShareType())
                .eq(param.getId() != null,
                        AqShare::getId, param.getId())
                .like(param.getTitle() != null,
                        AqShare::getTitle, param.getTitle())
                .orderByDesc(AqShare::getCreated);
        IPage<AqShare> page = iAqShareService.page(param.page(), wrapper);
        List<AqShare> records = page.getRecords();
        if (records.isEmpty() || param.getJwCloudUserId() == null) {
            return ResultSet.page(page);
        }
        Set<String> ids = records.stream().map(AqShare::getId).collect(Collectors.toSet());
        LambdaQueryWrapper<AqShareFavorites> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AqShareFavorites::getJwCloudUserId, param.getJwCloudUserId())
                .in(AqShareFavorites::getAqShareId, ids);
        List<AqShareFavorites> list = iAqShareFavoritesService.list(queryWrapper);
        for (AqShareFavorites aqShareFavorites : list) {
            for (AqShare record : records) {
                if (record.getId().equals(aqShareFavorites.getAqShareId())) {
                    record.setFavorites(true);
                }
            }
        }
        return ResultSet.page(page);
    }

    /**
     * 分享列表用户
     */
    @GetMapping("find-share-by-user-id")
    public ResultPage<AqShare> findShareByUserId(AqShareQ param) {
        QueryWrapper<AqShare> wrapper = new QueryWrapper<>();
        wrapper.eq(param.getShareType() != null,
                "asf.share_type", param.getShareType())
                .eq(param.getId() != null,
                        "asf.id", param.getId())
                .eq(param.getJwCloudUserId() != null,
                        "asf.jw_cloud_user_id", param.getJwCloudUserId())
                .eq("asf.is_del", 0)
                .like(param.getTitle() != null,
                        "asf.title", param.getTitle())
                .orderByDesc("asf.created");
        IPage<AqShare> page = iAqShareService.findPage(param.page(), wrapper);
        return ResultSet.page(page);
    }

    /**
     * 删除分享
     */
    @DeleteMapping("share-remove-by-id")
    public Result<?> shareRemoveById(@RequestParam String id) {
        boolean b = iAqShareService.removeById(id);
        return ResultSet.operation(b);
    }

    /**
     * 分享文件列表
     *
     * @param shareId 分享ID
     */
    @GetMapping("share-info")
    public Result<List<AqShareInfo>> findShareInfoByShareId(@RequestParam String shareId) {
        AqShare byId = iAqShareService.getById(shareId);
        if (!byId.getPermanent()) {
            Integer expiry = byId.getExpiry();
            Duration between = Duration.between(byId.getCreated(), LocalDateTime.now());
            long l = between.toMinutes();
            if (l >= expiry) {
                throw new BusinessException("分享已经过期");
            }
        }
        List<AqShareInfo> list = iAqShareService.findShareInfoByShareId(shareId);
        for (AqShareInfo aqShareInfo : list) {
            if (!aqShareInfo.getIsDir()) {
                String url = MinIoUtils.getObjectUrl(aqShareInfo.getFileMd5() + aqShareInfo.getSuffix(), 720);
                aqShareInfo.setFilePath(url);
            }
        }
        return ResultSet.go(list);
    }

    /**
     * 修改
     **/
    @PutMapping()
    public Result<?> rename(@RequestBody RenameVo param) {
        AqUpload byId = iAqUploadService.getById(param.getId());
        long count = iAqUploadService.countByFileNameAndDir(param.getFileName(), byId.getParentIds());
        if (count > 0) {
            if (iAqUploadService.renameOrFolderColor(param.getId(), param.getFolderColor())) {
                return ResultSet.go("文件夹颜色修改成功");
            }
        }
        AqUpload aqUpload = new AqUpload();
        aqUpload.setId(param.getId());
        aqUpload.setFileName(param.getFileName());
        aqUpload.setFolderColor(param.getFolderColor());
        boolean b = iAqUploadService.updateById(aqUpload);
        return ResultSet.operation(b);
    }

    /**
     * 新建文件夹
     */
    @PostMapping("new-folder")
    public Result<?> newFolder(@RequestBody @Validated NewFolder param) {
        long count = iAqUploadService.countByFileNameAndDir(param.getFileName(), param.getParentIds());
        if (count > 0) {
            return ResultSet.error("文件加名已存在");
        }
        AqUpload aqUpload = new AqUpload();
        BeanUtils.copyProperties(param, aqUpload);
        aqUpload.setIsDir(true);
        aqUpload.setUploadStatus(AqUploadStartEnum.UPLOAD_SUCCESS);
        aqUpload.setFileMd5(MD5Utils.encodeHexString(param.getFileName().getBytes(StandardCharsets.UTF_8)));
        boolean b = iAqUploadService.save(aqUpload);
        return ResultSet.operation(b);
    }

    /**
     * 文件上传到开发空间
     */
    @PostMapping("file-upload")
    public Result<String> fileUpload(@RequestParam("file") MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            String name = file.getOriginalFilename();
            long size = file.getSize();
            String contentType = file.getContentType();
            String url = MinIoUtils.uploadFilesToPublicSpace(inputStream, size, name, contentType);
            return ResultSet.go(url);
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("上传失败");
        }
    }

    /**
     * 多文件上传到开发空间
     */
    @PostMapping("file-upload-s")
    public Result<List<String>> fileUploadS(@RequestParam("file") MultipartFile[] file) {
        try {
            List<String> list = new ArrayList<>();
            for (MultipartFile f : file) {
                InputStream inputStream = f.getInputStream();
                String name = f.getOriginalFilename();
                long size = f.getSize();
                String contentType = f.getContentType();
                String url = MinIoUtils.uploadFilesToPublicSpace(inputStream, size, name, contentType);
                list.add(url);
            }

            return ResultSet.go(list);
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("上传失败");
        }
    }

    /**
     * 获取obj关联文件
     *
     * @param proId 实体ID
     */
    @GetMapping("get-obj-association-file")
    public Result<List<String>> getObjAssociationFile(@RequestParam String proId) {
        List<String> file = iAqFileService.getObjAssociationFile(proId);
        return ResultSet.go(file);
    }

    /**
     * 收藏
     */
    @PutMapping("favorites")
    public Result<?> favorites(@RequestBody AqShareFavorites param) {
        iAqShareFavoritesService.favorites(param.getJwCloudUserId(), param.getAqShareId());
        return ResultSet.success();
    }

    /**
     * 更新项目文件
     */
    @PutMapping("update-file")
    public Result<?> updateFile(@RequestBody @Validated UpdateFile param) {
        List<String> fileUrls = param.getFileUrls();
        List<AqFile> list = new ArrayList<>();
        for (String fileUrl : fileUrls) {
            AqFile aqFile = new AqFile();
            aqFile.setFileUrl(fileUrl);
            aqFile.setProId(param.getProId());
            list.add(aqFile);
        }
        LambdaQueryWrapper<AqFile> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AqFile::getProId, param.getProId());
        iAqFileService.remove(wrapper);
        iAqFileService.saveBatch(list);
        return ResultSet.success();
    }

    /**
     * fileMd5获取临时下载文件
     */
    @GetMapping("get-file-by-file-md5")
    public Result<String> getFileByFileMd5(@RequestParam String fileMd5) {
        String objectUrl = MinIoUtils.getObjectUrl(fileMd5, 1440);
        return ResultSet.go(objectUrl);
    }
}
